package com.gpt.article.service.impl.taskHandle.task;

import chatgpt.ChatGPT;
import chatgpt.entity.chat.ChatCompletion;
import chatgpt.entity.chat.ChatCompletionResponse;
import chatgpt.entity.chat.Message;
import com.alibaba.fastjson.JSON;
import com.gpt.article.controller.websocket.WebSocketUsers;
import com.gpt.article.domain.*;
import com.gpt.article.service.IAContentService;
import com.gpt.article.service.IGptTopicContentService;
import com.gpt.article.service.IGptTopicTitleService;
import com.gpt.article.service.IQContentService;
import com.gpt.article.service.impl.GptGenArticleTaskServiceImpl;
import com.gpt.article.service.impl.taskHandle.GenQContentTask;
import com.gpt.article.service.impl.taskHandle.GenTask;
import com.gpt.article.service.impl.taskHandle.GptRequstHelper;
import com.gpt.article.service.impl.taskHandle.helper.GptHelper;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import net.bytebuddy.implementation.bytecode.Throw;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.CountDownLatch;

@Service
public class GenQContentTasker {
    private static Logger logger = LoggerFactory.getLogger(GenQContentTasker.class);
    private static ChatCompletion chatCompletion;

    private static IQContentService qContentService;

    private static IAContentService aContentService;
    private static ISysDictTypeService sysDictTypeService;

    private static int tokenCount = 0;

    //已完成的回答的数量
    private static int completAContentNum = 0;

    //已完成的prompts数量
    private static int completQContentNum = 0;

    //成功的数量
    private static int successNum = 0;
    //失败的数量
    private static int errorNum = 0;

    //总执行数量
    private static int excuGenCount = 0;

    @Autowired
    private GptGenArticleTaskServiceImpl gptGenArticleTaskServiceImpl;

    public static int getCompletAContentNum() {
        return completAContentNum;
    }

    public static void setCompletAContentNum(int completAContentNum) {
        GenQContentTasker.completAContentNum = completAContentNum;
    }

    public static int getCompletQContentNum() {
        return completQContentNum;
    }

    public static void setCompletQContentNum(int completQContentNum) {
        GenQContentTasker.completQContentNum = completQContentNum;
    }

    public static int getExcuGenCount() {
        return excuGenCount;
    }

    public static void setExcuGenCount(int excuGenCount) {
        GenQContentTasker.excuGenCount = excuGenCount;
    }

    public static int getSuccessNum() {
        return successNum;
    }

    public static void setSuccessNum(int successNum) {
        GenQContentTasker.successNum = successNum;
    }

    public static int getErrorNum() {
        return errorNum;
    }

    public static void setErrorNum(int errorNum) {
        GenQContentTasker.errorNum = errorNum;
    }

    //    private static QContent qContent;
    @Autowired
    public void setISysDictTypeService(ISysDictTypeService sysDictTypeService) {
        GenQContentTasker.sysDictTypeService = sysDictTypeService;
    }

    @Autowired
    public void setIQContentService(IQContentService qContentService) {
        GenQContentTasker.qContentService = qContentService;
    }
    @Autowired
    public void setIAContentService(IAContentService aContentService) {
        GenQContentTasker.aContentService = aContentService;
    }


    public boolean genContent(QContent qContent, ChatGPT chatGPT, GenTask genTask, Long taskId){
        System.out.println(qContent+"!!!");
        if(ObjectUtils.isEmpty(qContent)){
            return false;
        }
        String prompts = qContent.getPrompts();
        Integer taskNum = genTask.getTaskNum();
        Integer allNum = genTask.getModelNum();
        String creteBy = genTask.getAcc();
        String useModels = qContent.getModelCodes();
        Map<String,Object> pmap = genTask.getPsMap();
        String qaType = String.valueOf(pmap.get("qaType"));

        GptFunPrompts gptFunPrompts = genTask.getGptFunPrompts();
        if(ObjectUtils.isEmpty(gptFunPrompts)){
            logger.error("检查数据库系统参数是否存在");
            return false;
        }

        Long qcontentId = qContent.getId();
        System.out.println(useModels+"~~~~");

        //定义返回结果
        String acontent = null;
        int thisModelTokenCount = 0;

        String models[] = useModels.split(",");
        List<SysDictData> dictModellist = sysDictTypeService.selectDictDataByType("gpt_model");
        if(models.length==0){
            System.out.println("选择所有模型进行生成");
            models = dictModellist.toArray(new String[dictModellist.size()]);
        }
        if(models.length==0){
            setErrorNum(getErrorNum()+1);
            new XiGaoTasker().upTask(taskId,getSuccessNum(),getErrorNum(),getCompletAContentNum(),"1");
            logger.error("genContent error: no model found");
            return false;
        }


        Boolean hasFail = false;
        System.out.println(models.length+"~~modelnum~~");
        for(String modelCode:models){
            acontent = "";
            //初始赋值返回结果
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("acontent",acontent);
            map.put("qcontentId",qcontentId);
            map.put("creteBy",creteBy);
            map.put("qatype",qaType);
            map.put("modelCode",modelCode);
            map.put("taskNum",taskNum);
            map.put("allNum",allNum);
            for(SysDictData dict:dictModellist){
                if(dict.getDictValue().equals(modelCode)){
                    map.put("modelName",dict.getDictLabel());
                }
            }
//            map.put("modelCode",mode);
            map.put("tokenCount",tokenCount);
            map.put("modelTokenCount",thisModelTokenCount);

            System.out.println("正在使用模型: " + modelCode + " in thread: " + Thread.currentThread().getName());
            setExcuGenCount(getExcuGenCount()+1);
            System.out.println("已执行数量22："+getExcuGenCount());
            Message user =  Message.of(prompts);
            System.out.println("333+");
            List messagesList  =  new ArrayList();
//                    Arrays.asList(user);
            Message systEmRole = null;
            String system = gptFunPrompts.getSystemRole();
            System.out.println("111+");
            if(!"null".equals(system)&&!StringUtils.isEmpty(system)){
                systEmRole = Message.ofSystem(system);
                if(!modelCode.startsWith("yi-")){
                    messagesList.add(systEmRole);
                }

            }
            System.out.println("122+");
            messagesList.add(user);
            System.out.println("12+++2+");
            System.out.println(gptFunPrompts+"~~~~~~~~~~~");
            int maxToken = gptFunPrompts.getMaxTokens();
            System.out.println("12++33333123+++"+maxToken);
            if(modelCode.startsWith("360GPT")||modelCode.startsWith("qwen")){
                System.out.println("12++66666+++");
                maxToken = 2000;
            }
            System.out.println("3333+");
            if(modelCode.startsWith("glm")||modelCode.startsWith("hunyuan")){
                System.out.println("333344+");
                chatCompletion = ChatCompletion.builder()
                        .model(modelCode)
//                    .model(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName())
//                    .messages(Arrays.asList(system,user))
                        .messages(messagesList)

//                    .maxTokens(GptHelper.calculateMaxToken(gptTopicTitle.getUseModel()))
                    .maxTokens(maxToken)
                     .build();
            }else if(modelCode.startsWith("bing")){
                System.out.println("123123+");
                chatCompletion =ChatCompletion.builder()
                        .model("bing")
//                .model(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName())
                        .messages(messagesList)
                        .maxTokens(maxToken)
                        .temperature(gptFunPrompts.getTemperature())
                        .build();
            }else if(modelCode.startsWith("ERNIE")){
                System.out.println("123123+");
                chatCompletion =ChatCompletion.builder()
                        .model(modelCode)
//                .model(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName())
                        .messages(messagesList)
//                .maxTokens(GptHelper.calculateMaxToken("ERNIE-Bot-8K"))
                        .temperature(gptFunPrompts.getTemperature())
                        .build();
            }else{
                System.out.println("123123+");
                chatCompletion = ChatCompletion.builder()
                        .model(modelCode)
//                    .model(ChatCompletion.Model.GPT_3_5_TURBO_16K.getName())
//                    .messages(Arrays.asList(system,user))
                        .messages(messagesList)
//                    .maxTokens(GptHelper.calculateMaxToken(gptTopicTitle.getUseModel()))
//                    .maxTokens(2000)
                        .maxTokens(maxToken)
                        .temperature(gptFunPrompts.getTemperature())
                        .topP(gptFunPrompts.getTopP())
                        .presencePenalty(gptFunPrompts.getPresencePenalty())
                        .frequencyPenalty(gptFunPrompts.getFrequencyPenalty())

                        .build();
            }

            System.out.println("123123+");

            logger.info("任务生成中...");
            long startTime = System.currentTimeMillis();
            ChatCompletionResponse response = null;
            try {
                response = chatGPT.chatCompletion(chatCompletion);
            }catch (Exception e){
                map.put("status","3");
                logger.error("生成出错：：：使用模型：：=="+modelCode+",prompts:"+prompts+",,emsg::"+e.getMessage());
                setErrorNum(getErrorNum()+1);
                hasFail = true;
                insertData(qContent,map,taskId,hasFail);
                continue;
            }

            long endTime = System.currentTimeMillis();
            long elapsedTime = endTime - startTime;
            logger.info("生成任务完成！耗时：{}",elapsedTime);


            if(ObjectUtils.isEmpty(response.getUsage())&&!modelCode.startsWith("bing")){
                //重试一次
                logger.error("任务生成失败，请检查余额或者模型是否正确");
                logger.error("生成出错：：：=-使用模型：："+modelCode+",prompts:"+prompts);
                setErrorNum(getErrorNum()+1);
                hasFail = true;
                insertData(qContent,map,taskId,hasFail);
                continue;
            }

            try {
                if(!modelCode.startsWith("bing")){
                    thisModelTokenCount = Integer.valueOf(String.valueOf(response.getUsage().getTotalTokens()));
                     map.put("modelTokenCount",thisModelTokenCount);
                }else{
                    map.put("modelTokenCount",0);
                }

            }catch (Exception e){
                setErrorNum(getErrorNum()+1);
                hasFail = true;
                insertData(qContent,map,taskId,hasFail);
                logger.error("获取token数量失败:{}",e.getMessage());
                continue;
            }
            //总共花费token
            tokenCount+=thisModelTokenCount;
            map.put("tokenCount",tokenCount);
//            promptCount+=Integer.valueOf(String.valueOf(response.getUsage().getPromptTokens()));
//            completionCount+= Integer.valueOf(String.valueOf(response.getUsage().getCompletionTokens()));

            Message res = response.getChoices().get(0).getMessage();
             acontent = res.getContent();
            logger.info("使用模型：{}",modelCode+",其中prompts:"+prompts);
            logger.info("回答：{}",acontent);

            if(StringUtils.isEmpty(acontent)){
                map.put("acontent",null);
                map.put("status","3");
                logger.error("生成出错：：：使用模型：="+modelCode+",prompts:"+prompts);
                setErrorNum(getErrorNum()+1);
                hasFail = true;
                insertData(qContent,map,taskId,hasFail);
            }
            map.put("acontent",acontent);

//             qcontentId = psMap.get("qcontentId").toString();
//            String creteBy = psMap.get("creteBy").toString();
//            Integer allNum = Integer.valueOf(psMap.get("allNum").toString());
//            Integer taskNum = Integer.valueOf(psMap.get("taskNum").toString());
//            String qatype = String.valueOf(psMap.get("qaType"));


            insertData(qContent,map,taskId,hasFail);
        }

        setCompletQContentNum(getCompletQContentNum()+1);

        return true;
    }



    public  Long insertData(QContent qContent,Map<String,Object> resMap,Long taskId,Boolean hasFail){
        System.out.println("准备写入数据.."+resMap.get("acontent"));
        Integer allNum = Integer.valueOf(resMap.get("allNum").toString());
        Integer taskNum = Integer.valueOf(resMap.get("taskNum").toString());
        String qatype = String.valueOf(resMap.get("qaType"));
        if("null".equals(qatype)){
            qatype ="0";
        }
        AContent aContent = null;

        Long qContentId = Long.valueOf(String.valueOf(resMap.get("qcontentId")));
        String qcontentstr = String.valueOf(resMap.get("modelCode"));
        AContent psAContent = new AContent();
        psAContent.setqContentId(qContentId);
        psAContent.setModelCode(qcontentstr);
        List<AContent> aContentList = aContentService.selectAContentList(psAContent);
        if(aContentList.size()>0){
            aContent = aContentList.get((aContentList.size()-1));
        }else{
            aContent = new AContent();
        }

        aContent.setqContentId(qContentId);
        if(StringUtils.isEmpty(String.valueOf(resMap.get("acontent")))){
            aContent.setaContent(null);
            aContent.setStatus("3");
        }else {
            aContent.setaContent(String.valueOf(resMap.get("acontent")));
            aContent.setStatus("2");
        }


        aContent.setQpType(qatype);
        aContent.setModelCode(String.valueOf(resMap.get("modelCode")));
        aContent.setModelName(String.valueOf(resMap.get("modelName")));
        aContent.setUseToken(Integer.valueOf(String.valueOf(resMap.get("modelTokenCount"))));
        aContent.setCreateBy(String.valueOf(resMap.get("creteBy")));

        //调整一个问题不会重复一个模型多次回答
        if(aContentList.size()>0){
            Long acontentId = qContent.getAcontentId();
            System.out.println("acontentId>"+acontentId);
            if(!"null".equals(acontentId)&&acontentId!=null){
                aContent.setId(acontentId);
            }
            aContentService.updateAContent(aContent);
        }else{
            aContentService.insertAContent(aContent);
        }


        setCompletAContentNum(getCompletAContentNum()+1);

        //已完成
        Integer completAContentNum = getCompletAContentNum();
        Integer completQContentNum = getCompletQContentNum();

        String statustr = "";
        String processstr = "";
        Integer excuCount = getExcuGenCount();
        boolean isComplete = false;
        if(taskNum>0&&excuCount>=allNum){
            statustr = "end";
            processstr = "任务已完成";
            System.out.println("任务完成...");
            isComplete = true;
        }else{
            if(allNum-getCompletAContentNum()==0){
                statustr = "end";
                processstr = "任务已完成";
                System.out.println("任务完成！...");

                isComplete = true;
            }else{
                statustr = "gening";
                isComplete = false;
                processstr= "正在使用【"+String.valueOf(resMap.get("modelCode"))+"】生成："+qContent.getPrompts();
            }
        }

        seedTxt(allNum,taskNum,statustr,processstr);

        if(!isComplete){
            new XiGaoTasker().upTask(taskId,getSuccessNum(),getErrorNum(),getCompletAContentNum(),"1");
        }else{
            new XiGaoTasker().upTask(taskId,getSuccessNum(),getErrorNum(),getCompletAContentNum(),"2");
        }



        qContent.setUseToken(Integer.valueOf(String.valueOf(resMap.get("tokenCount"))));
        if(hasFail){
            qContent.setGenStatus("3");
        }else{
            qContent.setGenStatus("2");
        }
        qContent.setUpdateTime(DateUtils.getNowDate());
        qContentService.updateQContent(qContent);
        return aContent.getId();
    }



    public  Boolean seedTxt(Integer allNum,Integer taskNum,String statustr,String processstr){
        Integer excuCount = getExcuGenCount();
        System.out.println("执行数量：：：："+excuCount);
        String  message = "任务提示:\n 当前需生成：prompts "+taskNum+"个，需生成的回答"+allNum+"个\n"
                +"剩余任务：prompts "+(taskNum-getCompletQContentNum())+"个，剩余回答"+(allNum-getCompletAContentNum())+"个\n"+
                "当前任务："+processstr+"(如果一直卡在这个界面可以尝试刷新页面)";
        Integer percentage = getCompletAContentNum()/allNum;
        Map<String,Object> msgmap = new HashMap<String,Object>();
        msgmap.put("message",message);
        msgmap.put("percentage",percentage);
        msgmap.put("acontentId",null);
        msgmap.put("status",statustr);

        String  jsonString = JSON.toJSONString(msgmap);
        WebSocketUsers.sendMessageToUsersByText(jsonString);
        return true;
    }


    /**
     * 重置执行数量
     * @return
     */
    public Boolean resetExcu(){
        GenQContentTasker.setCompletAContentNum(0);
        GenQContentTasker.setCompletQContentNum(0);
        GenQContentTasker.setExcuGenCount(0);
        GenQContentTasker.setSuccessNum(0);
        GenQContentTasker.setErrorNum(0);
        return true;
    }



}
